package com.lvmama.pangolin.core;

import com.github.pagehelper.PageHelper;
import com.lvmama.pangolin.busi.config.ConfigManager;
import com.lvmama.pangolin.entity.core.BaseCommodity;
import com.lvmama.pangolin.entity.core.BaseProduct;
import com.lvmama.pangolin.mybatis.mapper.BaseCommodityMapper;
import com.lvmama.pangolin.util.CommonCommodityUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

@Service
public class BaseCommodityService implements CommonCommodityService {
    @Autowired
    public CommonCommodityUtils commonCommodityUtils;

    @Autowired
    public BaseCommodityMapper baseCommodityMapper;

    private static final String BUSINESSCODE_HOTEL="HOTEL";//业务代码：酒店：HOTEL
    private static final String COMBINEDCOMMODITY_SYMBOL= "\\+\\、\\*";//组合票常常出现的符号
    private static final String COMBINEDCOMMODITY_PLUS= "+";//组合票常常出现的符号
    private static final String COMBINEDCOMMODITY_MUTIPLICATION= "*";//组合票常常出现的符号
    private static final String COMBINEDCOMMODITY_SLIGHT_PAUSE= "、";//组合票常常出现的符号

    /**
     * 两个商品名称相似度
     * @param base：标准商品
     * @param compareTo
     * @return
     */
    @Override
    public double nameSimilarity(BaseCommodity base, BaseCommodity compareTo) {
        return commonCommodityUtils.nameScore(base.getCommodityName(),compareTo.getCommodityName())*ONE_HUNDRED;
    }
    /**
     * 两个商品类型相似度
     * @param base：标准商品
     * @param compareTo
     * @return
     */
    @Override
    public double typeSimilarity(BaseCommodity base, BaseCommodity compareTo) {
        return commonCommodityUtils.typeScore(base.getCommodityType(),compareTo.getCommodityType())*ONE_HUNDRED;
    }
    /**
     * 两个商品价格相似度
     * @param base：标准商品
     * @param compareTo
     * @return
     */
    @Override
    public double priceSimilarity(BaseCommodity base, BaseCommodity compareTo) {
        return commonCommodityUtils.priceScore(base.getSalePrice().trim(),compareTo.getSalePrice().trim())*ONE_HUNDRED;
    }
    /**
     * 两个商品城市相似度
     * @param base：标准商品
     * @param compareTo
     * @return
     */
    @Override
    public double citySimilarity(BaseCommodity base, BaseCommodity compareTo) {
        return commonCommodityUtils.cityScore(base.getCityCode().trim(),compareTo.getCityCode().trim())*ONE_HUNDRED;
    }

    /**
     * 传入的两个字符串的相似度
     * @param baseName
     * @param compareToName
     * @return
     */
    public double scoreString(String baseName ,String compareToName)
    {
        return commonCommodityUtils.nameScore(baseName,compareToName)*ONE_HUNDRED;
    }

    /**
     * 根据通用产品查询未被关联的通用商品
     * 在实现该方法时，需要保证查询到的通用商品在commodity_rel表中不存在（即不存在关联）
     * @param baseProduct
     * @return
     */
    public List<BaseCommodity> selectCommodityByBaseProduct(BaseProduct baseProduct)
    {
        return baseCommodityMapper.selectCommodityByBaseProduct(baseProduct);
    }


    /**
     * 获得最佳匹配的商品，其中standard为标准产品，在list中寻找
     * 相似度最高的商品
     * @param standard
     * @param list
     * @return
     */
    public BaseCommodity getBestMatched(BaseCommodity standard ,List<BaseCommodity> list)
    {
        BaseCommodity bestMatch = null;
        if(list==null||list.isEmpty()||standard==null)
        {
            return bestMatch;
        }

        for(BaseCommodity bc : list)
        {
            /**
             * 过滤掉组合票
             */
            if(isCombinedBaseCommodity(bc))
            {
                continue;
            }
            double _nameScore = 0;
            if(BUSINESSCODE_HOTEL.equals(bc.getBusinessCode()))
            {   //特殊处理酒店的商品名称
                _nameScore = this.scoreString(bc.getCommodityType()
                        +bc.getCommodityName(),bc.getCommodityType()+bc.getCommodityName());
            }else{
                _nameScore = this.scoreString(bc.getCommodityName(),bc.getCommodityName());
            }
            double _typeScore = this.typeSimilarity(standard,bc);
            double _priceScore = this.priceSimilarity(standard,bc);
            double score = _nameScore*getNameFactor()+
                    _typeScore*getTypeFactor()+_priceScore*getPriceFactor();
            bc.setSortScore(score);
            bc.setNameScore(_nameScore);//设置名称评分
            bc.setTypeScore(_typeScore);//设置设置类型评分
            bc.setPriceScore(_priceScore);//设置价格评分
            bc.setCityScore(this.citySimilarity(standard,bc));//不参与打分
        }
        /**
         * 按照总评排序
         */
        sortBySortScore(list);
        /**
         * 在最大允许的次数中寻找最佳匹配
         */
        if(list.size()>=getCommodity_match_max_times())
        {
            for(BaseCommodity bc:list)
            {
                /**
                 * 当价格在合理偏差区间代表满足要求
                 */
                if(isAllowedPriceRange(standard.getSalePrice(),bc.getSalePrice(),
                        getDeviation(Double.valueOf(standard.getSalePrice()))))
                {
                    bestMatch = bc;
                    break;
                }
            }
        }
        return bestMatch;
    }



    /**
     * 根据sortScore进行排序
     * @return
     */
    public void sortBySortScore(List<BaseCommodity> needSortList)
    {
        if(needSortList==null||needSortList.isEmpty())
        {
            return;
        }
        Collections.sort(needSortList, new Comparator<BaseCommodity>() {
            @Override
            public int compare(BaseCommodity o1, BaseCommodity o2) {
                int ret = 0;
                if(o1.getSortScore()>o2.getSortScore())
                {
                    ret = -1;
                }
                if(o1.getSortScore()<o2.getSortScore())
                {
                    ret = 1;
                }
                return ret;
            }
        });
    }

    /**
     * 判断价格是否在基准价格的偏差允许范围内
     * @param basePrice
     * @param comparePrice
     * @param deviation
     * @return
     */
    public boolean isAllowedPriceRange(String basePrice ,String comparePrice ,double deviation)
    {
        boolean ret = false;
        double _basePrice = Double.valueOf(basePrice);
        double _comparePrice = Double.valueOf(comparePrice);
        if(_comparePrice<=(1+deviation)*_basePrice&&_comparePrice>=(1-deviation)*_basePrice)
        {
            ret = true;
        }
        return ret;
    }


    /**
     * 获取价格影响度因子
     * @return
     */
    public float getPriceFactor()
    {
        String _PRICE_FACTOR = ConfigManager.getInstance().getParamValue("COMMODITY_FACTOR_PRICE","COMMODITY_FACTOR_PRICE");
        return (_PRICE_FACTOR!=null&&!"".equals(_PRICE_FACTOR))?Float.valueOf(_PRICE_FACTOR):0.1F;
    }

    /**
     * 获取名称影响度因子
     * @return
     */
    public float getNameFactor()
    {
        String _NAME_FACTOR = ConfigManager.getInstance().getParamValue("COMMODITY_FACTOR_NAME","COMMODITY_FACTOR_NAME");
        return (_NAME_FACTOR!=null&&!"".equals(_NAME_FACTOR))?Float.valueOf(_NAME_FACTOR):0.8F;
    }

    /**
     * 获取类型影响度因子
     * @return
     */
    public float getTypeFactor()
    {
        String _TYPE_FACTOR = ConfigManager.getInstance().getParamValue("COMMODITY_FACTOR_TYPE","COMMODITY_FACTOR_TYPE");
        return (_TYPE_FACTOR!=null&&!"".equals(_TYPE_FACTOR))?Float.valueOf(_TYPE_FACTOR):0.1F;
    }


    /**
     * <h1>根据价格判断其允许的价格偏差度</h1>
     * <p>由于不同价格对于相同偏差度的反应不同：比如￥50元的商品可以允许70%的偏差（即：￥15-￥85在可接受的范围）</p>
     * <p>但￥1000元的商品，偏差度70%就不合适。</p>
     * <p>但￥1元-￥50的商品，偏差度建议 70%。</p>
     * <p>但￥51元-￥100的商品，偏差度建议 60%。</p>
     * <p>但￥101元-￥200的商品，偏差度建议 45%。</p>
     * <p>但￥201元-￥300的商品，偏差度建议 40%。</p>
     * <p>但￥301元-￥600的商品，偏差度建议 35%。</p>
     * <p>但￥601元-以上的商品，偏差度建议 30%。</p>
     * @param _price
     * @return
     */
    public float getDeviation(Double _price)
    {

        if(50>=_price&&_price>=0)
        {
            return getDeviation_half_hundred();

        }else if(100>=_price&&_price>50)
        {
            return  getdeviation_to_hundred();

        }else if(200>=_price&&_price>100)
        {
            return  getdeviation_between_one_two_hundred();

        }else if(300>=_price&&_price>200)
        {
            return  getdeviation_between_two_thr_hundred();

        }else if(600>=_price&&_price>300)
        {
            return  getdeviation_between_thr_six_hundred();

        }else if(_price>600)
        {
            return getdeviation_over_six_hundred();

        }else
        {
            return 0f;
        }
    }



    /**
     * 1-50价格区间的偏差度
     */
    public float getDeviation_half_hundred()
    {
        String _HALF_HUNDRED=ConfigManager.getInstance().getParamValue("DEVIATION_HALF_HUNDRED","DEVIATION_HALF_HUNDRED");
        return (_HALF_HUNDRED!=null&&!"".equals(_HALF_HUNDRED))?Float.valueOf(_HALF_HUNDRED):0.7f;
    }
    /**
     * 51-100价格区间的偏差度
     */
    public float getdeviation_to_hundred()
    {
        String _TO_HUNDRED=ConfigManager.getInstance().getParamValue("DEVIATION_TO_HUNDRED","DEVIATION_TO_HUNDRED");
        return (_TO_HUNDRED!=null&&!"".equals(_TO_HUNDRED))?Float.valueOf(_TO_HUNDRED):0.6F;
    }
    /**
     * 101-200价格区间的偏差度
     */
    public float getdeviation_between_one_two_hundred()
    {
        String _ONE_TWO_HUNDRED=ConfigManager.getInstance().getParamValue("DEVIATION_BETWEEN_ONE_TWO_HUNDRED","DEVIATION_BETWEEN_ONE_TWO_HUNDRED");
        return (_ONE_TWO_HUNDRED!=null&&!"".equals(_ONE_TWO_HUNDRED))?Float.valueOf(_ONE_TWO_HUNDRED):0.45F;
    }
    /**
     * 201-300价格区间的偏差度
     */
    public float getdeviation_between_two_thr_hundred()
    {
        String _TWO_THR_HUNDRED=ConfigManager.getInstance().getParamValue("DEVIATION_BETWEEN_TWO_THR_HUNDRED","DEVIATION_BETWEEN_TWO_THR_HUNDRED");
        return (_TWO_THR_HUNDRED!=null&&!"".equals(_TWO_THR_HUNDRED))?Float.valueOf(_TWO_THR_HUNDRED):0.4F;
    }
    /**
     * 301-600价格区间的偏差度
     */
    public float getdeviation_between_thr_six_hundred()
    {
        String _THR_SIX_HUNDRED=ConfigManager.getInstance().getParamValue("DEVIATION_BETWEEN_THR_SIX_HUNDRED","DEVIATION_BETWEEN_THR_SIX_HUNDRED");
        return (_THR_SIX_HUNDRED!=null&&!"".equals(_THR_SIX_HUNDRED))?Float.valueOf(_THR_SIX_HUNDRED):0.35F;

    }
    /**
     * 601以上的价格偏差度
     */
    public float getdeviation_over_six_hundred()
    {
        String _OVER_SIX_HUNDRED=ConfigManager.getInstance().getParamValue("DEVIATION_OVER_SIX_HUNDRED","DEVIATION_OVER_SIX_HUNDRED");
        return (_OVER_SIX_HUNDRED!=null&&!"".equals(_OVER_SIX_HUNDRED))?Float.valueOf(_OVER_SIX_HUNDRED):0.3F;
    }
    /**
     * 商品匹配评分最靠前的范围
     */
    public float getCommodity_match_max_times()
    {
        String _COMMODITY_MATCH_MAX_TIMES=ConfigManager.getInstance().getParamValue("COMMODITY_MATCH_MAX_TIMES","COMMODITY_MATCH_MAX_TIMES");
        return (_COMMODITY_MATCH_MAX_TIMES!=null&&!"".equals(_COMMODITY_MATCH_MAX_TIMES))?Integer.valueOf(_COMMODITY_MATCH_MAX_TIMES):5;
    }

    /**
     * 判断基本商品是否是组合票
     * @param baseCommodity
     * @return
     */
    public boolean isCombinedBaseCommodity(BaseCommodity baseCommodity)
    {
//        Pattern pattern = Pattern.compile(COMBINEDCOMMODITY_SYMBOL);
//        System.out.println(COMBINEDCOMMODITY_SYMBOL);
//        Matcher matcher = pattern.matcher(baseCommodity.getCommodityName());
//        return matcher.find();
        boolean ret = false ;
        if(baseCommodity==null)
        {
            return false;
        }
        if(baseCommodity.getCommodityName().indexOf(COMBINEDCOMMODITY_PLUS)>0
                ||baseCommodity.getCommodityName().indexOf(COMBINEDCOMMODITY_MUTIPLICATION)>0
                ||baseCommodity.getCommodityName().indexOf(COMBINEDCOMMODITY_SLIGHT_PAUSE)>0)
        {
            ret = true;
        }
        return ret;
    }
}
